﻿using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Bamboo.Utils
{
    /// <summary>
    /// 密码强度评分计算
    /// </summary>
    public class PasswordStrength
    {
        /// <summary>
        /// 输入的密码
        /// </summary>
        public string Password { get; private set; }
        /// <summary>
        /// 评分，0-100
        /// </summary>
        public int Rating { get; private set; }
        /// <summary>
        /// 强度等级，1-7，越高越强
        /// </summary>
        public int Level { get; private set; }
        /// <summary>
        /// 强度等级文字描述
        /// </summary>
        public string LevelText { get; private set; }

        public PasswordStrength(string pwd)
        {
            Password = pwd;
            //长度评分
            int rate1;
            if (pwd.Length <= 4) rate1 = 5;
            else if (pwd.Length >= 5 && pwd.Length <= 7) rate1 = 10;
            else rate1 = 25;
            //品种评分
            int smallLetterCount = 0;
            int bigLetterCount = 0;
            int digitCount = 0;
            int symbolCount = 0;
            string symbolList = "`~!@#$%^&*()_+-=[]\\{}|;':\"<>?,./";
            foreach (char ch in pwd)
            {
                if (ch >= 'a' && ch <= 'z') ++smallLetterCount;
                else if (ch >= 'A' && ch <= 'Z') ++bigLetterCount;
                else if (ch >= '0' && ch <= '9') ++digitCount;
                else if (symbolList.Contains(ch)) ++symbolCount;
            }
            //字母
            int rate2;
            if (smallLetterCount > 0 && bigLetterCount > 0) rate2 = 25;
            else if (smallLetterCount > 0 || bigLetterCount > 0) rate2 = 10;
            else rate2 = 0;
            //数字
            int rate3;
            if (digitCount == 0) rate3 = 0;
            else if (digitCount == 1) rate3 = 10;
            else rate3 = 25;
            //符号
            int rate4;
            if (symbolCount == 0) rate4 = 0;
            else if (symbolCount == 1) rate4 = 10;
            else rate4 = 25;
            //附加分
            bool hasLetter = (smallLetterCount > 0 || bigLetterCount > 0);
            bool hasBigLetter = bigLetterCount > 0;
            bool hasSmallLetter = smallLetterCount > 0;
            bool hasDigit = digitCount > 0;
            bool hasSymbol = symbolCount > 0;
            int exRate1 = hasLetter && hasDigit ? 2 : 0;
            int exRate2 = hasLetter && hasDigit && hasSymbol ? 3 : 0;
            int exRate3 = hasBigLetter && hasSmallLetter && hasDigit && hasSymbol ? 5 : 0;
            //总分
            this.Rating = rate1 + rate2 + rate3 + rate4 + exRate1 + exRate2 + exRate3;
            //强度等级
            if (Rating >= 90)      { Level = 5; LevelText = "(5)非常安全"; }
            else if (Rating >= 70) { Level = 4; LevelText = "(4)安全"; }
            else if (Rating >= 50) { Level = 3; LevelText = "(3)一般"; }
            else if (Rating >= 25) { Level = 2; LevelText = "(2)弱"; }
            else                   { Level = 1; LevelText = "(1)非常弱"; }
        }

        /// <summary>
        /// 获取密码强度说明文字
        /// </summary>
        /// <returns></returns>
        public static string GetIntroduce()
        {
            string ret = "一、密码长度:\r\n" +
            "5 分: 小于等于 4 个字符\r\n" +
            "10 分: 5 到 7 字符\r\n" +
            "25 分: 大于等于 8 个字符\r\n" +
            "\r\n" +
            "二、字母:\r\n" +
            "0 分: 没有字母\r\n" +
            "10 分: 全都是小（大）写字母\r\n" +
            "20 分: 大小写混合字母\r\n" +
            "\r\n" +
            "三、数字:\r\n" +
            "0 分: 没有数字\r\n" +
            "10 分: 1 个数字\r\n" +
            "20 分: 大于等于 3 个数字\r\n" +
            "\r\n" +
            "四、符号:\r\n" +
            "0 分: 没有符号\r\n" +
            "10 分: 1 个符号\r\n" +
            "25 分: 大于 1 个符号\r\n" +
            "\r\n" +
            "五、奖励:\r\n" +
            "2 分: 字母和数字\r\n" +
            "3 分: 字母、数字和符号\r\n" +
            "5 分: 大小写字母、数字和符号\r\n" +
            "\r\n" +
            "综合评分标准:\r\n" +
            ">= 90: 非常安全\r\n" +
            ">= 80: 安全（Secure）\r\n" +
            ">= 70: 非常强\r\n" +
            ">= 60: 强（Strong）\r\n" +
            ">= 50: 一般（Average）\r\n" +
            ">= 25: 弱（Weak）\r\n" +
            ">= 0: 非常弱";
            return ret;
        }
    }
}
